# partial --== Decompile ==-- with fixes
import Live
from TransportComponent import TransportComponent
from _Framework.ButtonElement import ButtonElement
from _Framework.EncoderElement import EncoderElement #added

class AddlTransportComponent(TransportComponent):
    __doc__ = ' TransportComponent that only uses certain buttons if a shift button is pressed '
    def __init__(self):
        TransportComponent.__init__(self)
        self._shift_button = None
        self._shift_pressed = False
        self._undo_button = None #added from OpenLabs SpecialTransportComponent script
        self._redo_button = None #added from OpenLabs SpecialTransportComponent script
        self._bts_button = None #added from OpenLabs SpecialTransportComponent script
        self._tempo_encoder_control = None #new addition
        return None

    def disconnect(self):
        TransportComponent.disconnect(self)
        if self._shift_button != None:
            self._shift_button.remove_value_listener(self._shift_value)
            self._shift_button = None
        if (self._undo_button != None): #added from OpenLabs SpecialTransportComponent script
            self._undo_button.remove_value_listener(self._undo_value)
            self._undo_button = None
        if (self._redo_button != None): #added from OpenLabs SpecialTransportComponent script
            self._redo_button.remove_value_listener(self._redo_value)
            self._redo_button = None
        if (self._bts_button != None): #added from OpenLabs SpecialTransportComponent script
            self._bts_button.remove_value_listener(self._bts_value)
            self._bts_button = None
        if (self._tempo_encoder_control != None): #new addition
            self._tempo_encoder_control.remove_value_listener(self._tempo_encoder_value)
            self._tempo_encoder_control = None
        return None

    def set_shift_button(self, button):
        if not(button == None or isinstance(button, ButtonElement) and button.is_momentary()):
            isinstance(button, ButtonElement)
            raise AssertionError
        if self._shift_button != button:
            if self._shift_button != None:
                self._shift_button.remove_value_listener(self._shift_value)
            self._shift_button = button
            if self._shift_button != None:
                self._shift_button.add_value_listener(self._shift_value)
            self._rebuild_callback()
            self.update()
        return None

   

    def update(self):
        self._on_metronome_changed()
        self._on_overdub_changed()
        self._on_nudge_up_changed() #added
        self._on_nudge_down_changed #added

    def _shift_value(self, value):
        if not self._shift_button != None:
            raise AssertionError
        if not value in range(128):
            raise AssertionError
        self._shift_pressed = value != 0
        if self.is_enabled():
            self.is_enabled()
            self.update()
        else:
            self.is_enabled()
        return None

    def _metronome_value(self, value):
        if not self._shift_pressed:
        ##if self._shift_pressed: 
            TransportComponent._metronome_value(self, value)


    def _overdub_value(self, value):
        if not self._shift_pressed:
            TransportComponent._overdub_value(self, value)


    def _nudge_up_value(self, value): #added
        if not self._shift_pressed:
            TransportComponent._nudge_up_value(self, value)
            

    def _nudge_down_value(self, value): #added
        if not self._shift_pressed:
            TransportComponent._nudge_down_value(self, value)            
            
            
    def _tap_tempo_value(self, value): # Added as Shift + Tap Tempo
        if not self._shift_pressed:
        #if self._shift_pressed:
            TransportComponent._tap_tempo_value(self, value)


    def _quant_toggle_value(self, value):
        assert (self._quant_toggle_button != None)
        assert (value in range(128))
        assert (self._last_quant_value != Live.Song.RecordingQuantization.rec_q_no_q)
        if (self.is_enabled() and (not self._shift_pressed)):
            if ((value != 0) or (not self._quant_toggle_button.is_momentary())):
                quant_value = self.song().midi_recording_quantization
                if (quant_value != Live.Song.RecordingQuantization.rec_q_no_q):
                    self._last_quant_value = quant_value
                    self.song().midi_recording_quantization = Live.Song.RecordingQuantization.rec_q_no_q
                else:
                    self.song().midi_recording_quantization = self._last_quant_value


    def _on_metronome_changed(self):
        if not self._shift_pressed:
        #if self._shift_pressed:
            TransportComponent._on_metronome_changed(self)


    def _on_overdub_changed(self):
        if not self._shift_pressed:
            TransportComponent._on_overdub_changed(self)


    def _on_nudge_up_changed(self): #added
        if not self._shift_pressed:
            TransportComponent._on_nudge_up_changed(self)


    def _on_nudge_down_changed(self): #added
        if not self._shift_pressed:
            TransportComponent._on_nudge_down_changed(self)


   
    """ from OpenLabs module SpecialTransportComponent """
    
    def set_undo_button(self, undo_button):
		assert isinstance(undo_button, (ButtonElement,
										type(None)))
		if (undo_button != self._undo_button):
			if (self._undo_button != None):
				self._undo_button.remove_value_listener(self._undo_value)
			self._undo_button = undo_button
			if (self._undo_button != None):
				self._undo_button.add_value_listener(self._undo_value)
			self.update()



    def set_redo_button(self, redo_button):
		assert isinstance(redo_button, (ButtonElement,
										type(None)))
		if (redo_button != self._redo_button):
			if (self._redo_button != None):
				self._redo_button.remove_value_listener(self._redo_value)
			self._redo_button = redo_button
			if (self._redo_button != None):
				self._redo_button.add_value_listener(self._redo_value)
			self.update()


    def set_bts_button(self, bts_button): #"back to start" button
        assert isinstance(bts_button, (ButtonElement,
                                       type(None)))
        if (bts_button != self._bts_button):
            if (self._bts_button != None):
                self._bts_button.remove_value_listener(self._bts_value)
            self._bts_button = bts_button
            if (self._bts_button != None):
                self._bts_button.add_value_listener(self._bts_value)
            self.update()


    def _undo_value(self, value):
        if not self._shift_pressed: #added
            assert (self._undo_button != None)
            assert (value in range(128))
            if self.is_enabled():
                if ((value != 0) or (not self._undo_button.is_momentary())):
                    if self.song().can_undo:
                        self.song().undo()


    def _redo_value(self, value):
        if not self._shift_pressed: #added
            assert (self._redo_button != None)
            assert (value in range(128))
            if self.is_enabled():
                if ((value != 0) or (not self._redo_button.is_momentary())):
                    if self.song().can_redo:
                        self.song().redo()


    def _bts_value(self, value):
        assert (self._bts_button != None)
        assert (value in range(128))
        if self.is_enabled():
            if ((value != 0) or (not self._bts_button.is_momentary())):
                self.song().current_song_time = 0.0
     
        
    def _tempo_encoder_value(self, value):
        ##if not self._shift_pressed:
        if self._shift_pressed:
            assert (self._tempo_encoder_control != None)
            assert (value in range(128))
            backwards = (value >= 64)
            step = 0.1 #step = 1.0 #reduce this for finer control; 1.0 is 1 bpm
            if backwards:
                amount = (value - 128)
            else:
                amount = value
            tempo = max(20, min(999, (self.song().tempo + (amount * step))))
            self.song().tempo = tempo

            
        
    def set_tempo_encoder(self, control):
        assert ((control == None) or (isinstance(control, EncoderElement) and (control.message_map_mode() is Live.MidiMap.MapMode.relative_two_compliment)))
        if (self._tempo_encoder_control != None):
            self._tempo_encoder_control.remove_value_listener(self._tempo_encoder_value)
        self._tempo_encoder_control = control
        if (self._tempo_encoder_control != None):
            self._tempo_encoder_control.add_value_listener(self._tempo_encoder_value)
        self.update()